package user

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"go-zero-project/common/excption"
	"go-zero-project/services/user/rpc/constans"
	"go-zero-project/services/user/rpc/internal/mapper"
	"go-zero-project/services/user/rpc/internal/mapper/bo"
	"go-zero-project/services/user/rpc/internal/svc"
	"go-zero-project/services/user/rpc/pb"

	"github.com/zeromicro/go-zero/core/logx"
)

type LoginLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginLogic {
	return &LoginLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *LoginLogic) Login(in *pb.LoginReq) (*pb.LoginResp, error) {
	// 1.query user in db...
	userBo := bo.UserInfoBO{}
	userBo.Username = in.Username
	userMapper := mapper.NewUserMapper()
	userEntity, err := userMapper.SelectOne(l.svcCtx.DBEngin, userBo)
	if err != nil {
		if err.Error() == "record not found" {
			return nil, excption.NewErrCode(constans.UserNoExistError)
		}
		logx.Errorf("select user entity err:%s", err.Error())
		return nil, err
	}
	// 2. check user
	if userEntity.UserId < 0 {
		return nil, excption.NewErrCode(constans.UserNoExistError)
	}
	if ok := userEntity.Status != constans.UserStatusNormal; ok {
		return nil, excption.NewErrCode(constans.UserDisableErr)
	}
	hash := sha256.New()
	hash.Write([]byte(in.Password + userEntity.Salt))
	encodeToString := hex.EncodeToString(hash.Sum(nil))
	// d6fbdc979cb06dbd532d98a3a0b39fb6c3e66d0aa727fe4e44f8545415858ddf
	if encodeToString != userEntity.Password {
		return nil, excption.NewErrCode(constans.PasswordErr)
	}
	// 2. generateToken...
	generateTokenLogic := NewGenerateTokenLogic(l.ctx, l.svcCtx)
	generateToken, err := generateTokenLogic.GenerateToken(&pb.GenerateTokenReq{
		UserId: userEntity.UserId,
	})
	if err != nil {
		logx.Errorf("create token fail :%s", err.Error())
		return nil, excption.NewErrCode(constans.CreateTokenError)
	}
	// 3.return obj...
	return &pb.LoginResp{AccessToken: generateToken.AccessToken,
		AccessExpire: generateToken.AccessExpire,
		RefreshAfter: generateToken.RefreshAfter}, nil
}
